/**
 * Copyright 1996 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 *
 * Note, this is a very old runtime library that I have evolved since 1996. I rarely use it
 * now because the Apache Commons project has made it obsolete.
 */
/**
 * Copyright (C) 2003 by Self Technologies. All rights reserved.
 *
 * This software is the proprietary information of Self Technologies, Pty Ltd.
 * Use is subject to license terms.
 */
package self.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import self.io.StringInputStream;
import self.lang.StringUtils;

/**
 * What: an extension of the properties concept but with additional support for
 * entries that are listed in optional sections.
 * 
 * Why: properties format is a great format for name/value pairs, but sometimes
 * a combined name-value pair and list format is the desired descriptor format.
 * 
 * When: use this format when one requires a descriptor with the following
 * format:<br/>
 * name1=value1<br/>
 * name2=value2<br/>
 * <br/>
 * [section1]<br/>
 * entry3<br/>
 * entry4<br/>
 * <br/>
 * [section2]<br/>
 * entry5<br/>
 * entry6<br/>
 */
public class SectionListsProperties extends Properties {
	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
	final static public String[] ANNOTATIONS = {"[", "]"};
	
	private HashMap sectionLists = new HashMap();

	public void load(InputStream in) throws IOException {
		StringBuffer buffProps = new StringBuffer();
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		List sectionList = acquireSectionList("root");
		try {
			String line;
			while ((line = br.readLine()) != null) {
				String trimmedLine = line.trim();
				if (StringUtils.isNullOrEmpty(trimmedLine)
						|| trimmedLine.startsWith("#"))
					continue;
				if (trimmedLine.startsWith(ANNOTATIONS[0]) && trimmedLine.endsWith(ANNOTATIONS[1])) {
					String section = trimmedLine.substring(1, trimmedLine
							.length() - 1);
					sectionList = acquireSectionList(section);
					continue;
				}
				if (trimmedLine.indexOf("=") > -1)
					buffProps.append(line).append("\r\n");
				else
					sectionList.add(trimmedLine);
			}
			loadRootProperties(buffProps.toString());
		} finally {
			br.close();
		}
	}
	
	public Set getSectionsSet() {
		return sectionLists.keySet();
	}

	public List getSectionList(String section) {
		List ret = (List) sectionLists.get(section);
		if (ret == null)
			ret = Collections.EMPTY_LIST;
		return ret;
	}

	private void loadRootProperties(String propsAsStr) throws IOException {
		StringInputStream in = new StringInputStream(propsAsStr);
		try {
			super.load(in);
		} finally {
			in.close();
		}
	}

	private List acquireSectionList(String section) {
		List ret = (List) sectionLists.get(section);
		if (ret == null) {
			ret = new ArrayList();
			sectionLists.put(section, ret);
		}
		return ret;
	}
}
